今天有人问我一道 Java 面试题,是关于 Java 的类型系统的。我觉得这道题很有意思,所以写下来分享给大家。
题目是这样的:下面的 Java 代码会输出什么?
public class Test {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
System.out.println(s1.equals(s3));
System.out.println(s3.equals(s4));
}
}
这道题考查的是 Java 程序员对 String 类型和 == 操作符的理解。
首先我们需要理解 Java 中的字符串池(String Pool)机制。在 Java 中,字符串字面量(比如 "Hello")会被存储在字符串池中。当使用字符串字面量创建字符串时,JVM 会首先检查字符串池中是否已经存在相同的字符串。如果存在,则直接返回池中字符串的引用;如果不存在,则在池中创建新的字符串,然后返回引用。
所以对于 s1 和 s2,它们都是通过字符串字面量 "Hello" 创建的。由于字符串池中已经存在 "Hello",所以 s1 和 s2 实际上指向同一个对象。因此 s1 == s2 的结果是 true。
而对于 s3 和 s4,它们是通过 new String("Hello") 创建的。每次使用 new 关键字都会在堆内存中创建一个新的对象,即使内容相同,它们也是不同的对象。所以 s3 == s4 的结果是 false。
== 操作符比较的是对象的引用(地址),而 equals 方法比较的是对象的内容。String 类重写了 equals 方法,使其比较字符串的内容而不是引用。
因此,程序的输出应该是:
true
false
false
true
true
这道题虽然简单,但反映了 Java 类型系统中一个重要的概念:引用类型和值类型的区别,以及 == 操作符和 equals 方法的区别。理解这些概念对于编写正确的 Java 程序非常重要。
顺便说一句,Java 的类型系统设计得并不完美。它在基本类型(int, char 等)和引用类型(String, Object 等)之间做出了区分,导致了很多混淆。相比之下,一些现代语言(如 C#)提供了更好的统一类型系统。